package io.task.cc.message.socket.spi.server;

import io.task.cc.message.socket.Io;
import io.task.cc.message.socket.ReadCompletionHandler;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

@Slf4j
@Setter
@Getter
public class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Server> {


    public AcceptCompletionHandler() {
    }

    @Override
    public void completed(AsynchronousSocketChannel asynchronousSocketChannel, Server server) {
        try {
            ServerConfig serverConfig = server.getServerConfig();
            InetSocketAddress inetSocketAddress = (InetSocketAddress) asynchronousSocketChannel.getRemoteAddress();
            String clientIp = inetSocketAddress.getHostString();


            if (Io.IpBlacklist.contains(clientIp)) {
                log.info("{}在黑名单中, {}", clientIp, serverConfig.getName());
                asynchronousSocketChannel.close();
                return;
            }


            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 64 * 1024);
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_SNDBUF, 64 * 1024);
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);

            ServerChannelContext channelContext = new ServerChannelContext(serverConfig, asynchronousSocketChannel);
            channelContext.setClosed(false);
            channelContext.stat.setTimeFirstConnected(System.currentTimeMillis());
            channelContext.setServerNode(server.getServerNode());

            //			channelContext.traceClient(ChannelAction.CONNECT, null, null);

            //			tioServerConfig.connecteds.add(channelContext);
            serverConfig.ips.bind(channelContext);


            if (!server.isWaitingStop()) {
                ReadCompletionHandler readCompletionHandler = channelContext.getReadCompletionHandler();
                ByteBuffer readByteBuffer = readCompletionHandler.getReadByteBuffer();//ByteBuffer.allocateDirect(channelContext.tioConfig.getReadBufferSize());
                readByteBuffer.position(0);
                readByteBuffer.limit(readByteBuffer.capacity());
                asynchronousSocketChannel.read(readByteBuffer, readByteBuffer, readCompletionHandler);
            }
        } catch (Throwable e) {
            log.error("", e);
        } finally {
            if (server.isWaitingStop()) {
                log.info("{}即将关闭服务器，不再接受新请求", server.getServerNode());
            } else {
                AsynchronousServerSocketChannel serverSocketChannel = server.getServerSocketChannel();
                serverSocketChannel.accept(server, this);
            }
        }
    }

    @Override
    public void failed(Throwable exc, Server server) {
        AsynchronousServerSocketChannel serverSocketChannel = server.getServerSocketChannel();
        serverSocketChannel.accept(server, this);

        log.error("[" + server.getServerNode() + "]监听出现异常", exc);

    }

}
